/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Future;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.Timer;

import parsing.yago.IParserProgress;
import parsing.yago.YagoParser;
import core.exceptions.DBAccessException;
import core.exceptions.ParserException;
import core.threads.ThreadCallable;
import core.threads.ThreadPool;
import db.DBAccessEngine;
import db.IConstructDBProgress;

/**
 *
 * @author abadi
 */
public class JFrameConstructDB extends javax.swing.JFrame {

    private JFrame parentFrame;
    private Future<Void> parsingThread = null;

    /**
     * Creates new form JFrameConstructDB
     */
    public JFrameConstructDB(JFrame parentFrame) {
        this.parentFrame = parentFrame;
        initComponents();
        setLocationRelativeTo(null);
        GUIUtils.setJComponentFontAndColor(jLabelOverall, 13);
        GUIUtils.setJComponentFontAndColor(jLabelFile, 13);
        GUIUtils.setJComponentFontAndColor(jLabelElapsedTime, 13);
        GUIUtils.setJComponentFontAndColor(jLabelElapsedTimeTitle, 13);
        setVisible(true);
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this
     * code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanelMain = new javax.swing.JPanel();
        jButtonCancel = new javax.swing.JButton();
        jLabelElapsedTimeTitle = new javax.swing.JLabel();
        jLabelElapsedTime = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Loan-a-Book");
        setBackground(new java.awt.Color(51, 153, 255));
        setMinimumSize(new java.awt.Dimension(381, 198));
        setResizable(false);

        try {
			setIconImage(ImageIO.read(JFrameConstructDB.class.getResourceAsStream("/resources/icon.png")));
		} catch (IOException exception) {
			//do nothing, let java default icon take over
		}
        
        jPanelMain.setBackground(new java.awt.Color(51, 153, 255));

        jProgressBarOverall.setStringPainted(true);

        jProgressBarFile.setStringPainted(true);

        jLabelFile.setText("File Progress:");

        jButtonCancel.setText("Cancel");
        jButtonCancel.addActionListener(new java.awt.event.ActionListener() {
            @Override
			public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonCancelActionPerformed(evt);
            }
        });

        jLabelElapsedTimeTitle.setText("Elapsed Time:");

        javax.swing.GroupLayout jPanelMainLayout = new javax.swing.GroupLayout(jPanelMain);
        jPanelMain.setLayout(jPanelMainLayout);
        jPanelMainLayout.setHorizontalGroup(
            jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelMainLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jProgressBarOverall, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabelOverall, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jProgressBarFile, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabelFile, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelMainLayout.createSequentialGroup()
                        .addComponent(jLabelElapsedTimeTitle)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabelElapsedTime, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 99, Short.MAX_VALUE)
                        .addComponent(jButtonCancel)))
                .addContainerGap())
        );
        jPanelMainLayout.setVerticalGroup(
            jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelMainLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabelOverall, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBarOverall, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelFile, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBarFile, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(27, 27, 27)
                .addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanelMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jButtonCancel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabelElapsedTimeTitle))
                    .addComponent(jLabelElapsedTime, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanelMain, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCancelActionPerformed
        dispose();
    }//GEN-LAST:event_jButtonCancelActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void runGUI(final JFrame parentFrame) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(JFrameConstructDB.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(JFrameConstructDB.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(JFrameConstructDB.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(JFrameConstructDB.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
			public void run() {
                JFrameConstructDB jfcdb = new JFrameConstructDB(parentFrame);
                jfcdb.construct();
                jfcdb.implementTimer();
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private static javax.swing.JButton jButtonCancel;
    private javax.swing.JLabel jLabelElapsedTime;
    private javax.swing.JLabel jLabelElapsedTimeTitle;
    private final javax.swing.JLabel jLabelFile = new javax.swing.JLabel();
    private final javax.swing.JLabel jLabelOverall = new javax.swing.JLabel();
    private javax.swing.JPanel jPanelMain;
    private final javax.swing.JProgressBar jProgressBarFile = new javax.swing.JProgressBar();
    private final javax.swing.JProgressBar jProgressBarOverall = new javax.swing.JProgressBar();
    // End of variables declaration//GEN-END:variables

    @Override
    public void dispose() {
    	if (parsingThread != null)
    		parsingThread.cancel(true);
        parentFrame.setVisible(true);
        try {
        	super.dispose();
        } catch (Exception e) {
        	//thread may have caused disposal already
        }
    }

    void implementTimer(){
        final long start = System.currentTimeMillis();
        Timer time = new Timer(1000, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                long time = (System.currentTimeMillis() - start);
                    int minutes = (int) (time / 60000);
                    int seconds = (int) time - (minutes * 60000);
                    jLabelElapsedTime.setText(String.format("%02d:%02d", time / 60000, seconds / 1000));
            }
        });
        time.start();
    }
    
    void construct() {
    	
    	final JFrameConstructDB thisObj = this;
        final YagoParser parser = YagoParser.getParser();

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fileChooser.setDialogTitle("Select the directory where your YAGO files are kept: ");
        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
        	File dir = fileChooser.getSelectedFile();
        	if (!dir.isDirectory()) {
        		GUIUtils.showMessageError(new Exception("You must choose a directory", null), this);
        		dispose();
        		return;
        	}
            parser.setDirectory(dir.getPath());
        } else {
        	//user aborted:
        	dispose();
        	return;
        }
        
    	parsingThread = ThreadPool.submitTask(new ThreadCallable<Future<Void>, Void>() {
            @Override
            public Void call() throws Exception {

                parser.setParserProgress(parserProgress);
                
                try {
                    parser.parse();
                    DBAccessEngine.constructDatabase(constructProgress);
                } catch (ParserException e) {
                	GUIUtils.showMessageError(new DBAccessException(e.getMessage(), e), thisObj);
                	jButtonCancel.doClick();
                } catch (DBAccessException e) {
                	GUIUtils.showMessageError(e, thisObj);
                	jButtonCancel.doClick();
                }
                
                return null;
            }
        });
        
    }
    private IParserProgress parserProgress = new IParserProgress() {
        @Override
        public void workingOnFile(String name) {
            jLabelOverall.setText("Parsing " + name + "...");
        }

        @Override
        public void overallProgress(float percentage) {
            jProgressBarOverall.setValue((int) percentage);
        }

        @Override
        public void fileProgress(float percentage) {
            jProgressBarFile.setValue((int) percentage);
        }
    };
    private IConstructDBProgress constructProgress = new IConstructDBProgress() {
        @Override
        public void storingData(String msg) {
            jLabelOverall.setText(msg);
        }

        @Override
        public void progress(int progress) {
            jProgressBarFile.setValue(progress);
        }

        @Override
        public void initDBFinished(int progress) {
            jProgressBarFile.setValue(progress);
        }

        @Override
        public void done() {
            jButtonCancel.doClick();
        }
    };
}
